package SocialMediaSentiment;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

public class Perceptron extends StandardFunctions {
	static Map<String, Double> woordenweightslijst = getWeightsListOLD(0);

	public static void main(String args[]) throws IOException {
		testPerceptronMultiTweet.test();
	}

	// hasmap tweets contains <String tweet, int sentiment>
	public static void PerceptronMultiTweet(HashMap<String, Integer> tweets, double alpha, int iterations) {

		String tweet;
		double tweetValue = 0;
		double error = 0;
		double weight;
		int tweetClass; //also known as sentiment
		Map<String, Double> tweetWordWeights;
		Iterator<String> k;
		for (int i = 0; i < iterations; i++) {
			k = (Iterator<String>) tweets.keySet().iterator();
			while (k.hasNext()) {
				tweet = k.next();

				tweetWordWeights = getWeights(tweet, woordenweightslijst);//find the weights of the words used in the tweet
				tweetValue = CalculateTweetValue(tweetWordWeights, tweet); //calc the tweetValue
				tweetClass = tweets.get(tweet);//find what the real sentiment is.

				error = tweetClass - tweetValue;//the difference between the class and the calculated tweet value.
				for (String word : tweetWordWeights.keySet()) {
					weight = tweetWordWeights.get(word);
					weight += alpha*error;

					woordenweightslijst.put(word, weight);
				}

			}
			//System.out.println(i);
		}


		woordenweightslijst = scaleWeightList(woordenweightslijst);
		writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsList.txt");



	}

	public static void PerceptronMultiTweet(HashMap<String, Integer> tweets, double alpha) {
		Boolean optimized = false;
		String tweet;
		double tweetValue = 0;
		double error = 0;
		double weight;
		float bounderie1 = 0.27f,bounderie2 = -0.14f;
		float[] bounderies={bounderie1,bounderie2,0f};
		int tweetClass;//also known as sentiment
		Map<String, Double> tweetWordWeights;
		Iterator<String> k;
		int count = 1;
		if (count>1)
		{
			woordenweightslijst.clear();
			woordenweightslijst = getWeightsListOLD(1);
		}
		while(!optimized) {
			k = (Iterator<String>) tweets.keySet().iterator();
			while (k.hasNext()) {
				tweet = k.next();

				tweetWordWeights = getWeights(tweet, woordenweightslijst); //find the weights of the words used in the tweet
				tweetValue = CalculateTweetValue(tweetWordWeights, tweet); //calc the tweetValue
				tweetValue = convertExpectedTweetValueToClass(tweetValue, bounderies);
				tweetClass = tweets.get(tweet); //find what the real sentiment is.

				//the difference between the class and the calculated tweet value.
				error = Math.abs( (tweetClass+1) - (tweetValue+1) );
				error = (tweetClass>0)?error:-error;
				for (String word : tweetWordWeights.keySet()) {
					weight = tweetWordWeights.get(word);
					weight += alpha*error;

					woordenweightslijst.put(word, weight);
				}

			}

			writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsList.txt");
			System.out.println("written to file");
			try {
				bounderies = calcBounderies(bounderie1,bounderie2, woordenweightslijst);
			} catch (IOException e) {
				e.printStackTrace();
			}
			bounderie1 = bounderies[0];

			bounderie2 = bounderies[1];
			System.out.println(count++ + " "+bounderies[0]+" "+bounderies[1]+" "+bounderies[2]);

			bounderie2 = bounderies[1];
			System.out.println(count++ +" "+bounderies[0]+" "+bounderies[1]+" "+bounderies[2]);
		}


		woordenweightslijst = scaleWeightList(woordenweightslijst);
		writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsList.txt");



	}

	public static void PerceptronMultiTweetSentiment(HashMap<String, Integer> tweets, double alpha) {
		try {
			HashMap<Integer, String[]> woordenlijstSentiment = ReadExcel.read("CompareZeroNonZero.xls", 0,1);
			String[] woordenlijstSentimentData;
			String word;
			double weight;
			Iterator<Integer> k = woordenlijstSentiment.keySet().iterator();
			woordenweightslijst.clear();
			while(k.hasNext()){
				woordenlijstSentimentData = woordenlijstSentiment.get(k.next());
				word = woordenlijstSentimentData[0];
				weight = Double.parseDouble(woordenlijstSentimentData[1].replace(",", "."));
				woordenweightslijst.put(word, weight);
			}

			Boolean optimized = false;
			String tweet;
			float tweetValue = 0f;
			double error = 0;
			float boundery=0.5f,lastError = 0;
			int tweetClass; //also known as sentiment
			int index = 1;
			Map<String, Double> tweetWordWeights;
			Iterator<String> k1;
			HashMap<Integer,Float[]> tweetData= new HashMap<Integer, Float[]>();
			Float[] tweetValues = new Float[2];
			float[] bounderyError = new float[2];
			int count = 1;
			if (count>1)
			{
				woordenweightslijst.clear();
				woordenweightslijst = getWeightsListOLD(2);
			}
			while(!optimized) {
				k1 = (Iterator<String>) tweets.keySet().iterator();
				while (k1.hasNext()) {
					tweet = k1.next();

					tweetWordWeights = getWeights(tweet, woordenweightslijst); //find the weights of the words used in the tweet
					tweetValue = (float)CalculateTweetValue(tweetWordWeights, tweet); //calc the tweetValue
					//tweetValue = convertExpectedTweetValueToClassSentiment(tweetValue, boundery);
					tweetClass = tweets.get(tweet);//find what the real sentiment is.
					tweetValues[0] = (float) 0;
					tweetValues[1] = (float) 1;
					tweetData.put(index++,tweetValues);
					//the difference between the class and the calculated tweet value.
					error = Math.abs( (tweetClass+1) - (tweetValue+1) );
					error = (tweetClass>0)?error:-error;
					for (String tweetWord : tweetWordWeights.keySet()) {
						weight = tweetWordWeights.get(tweetWord);
						weight += alpha*error;

						woordenweightslijst.put(tweetWord, weight);
					}

				}

				writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsListSentiment.txt");
				System.out.println("written to file");
				try {
					bounderyError = bounderyCalculator.calcBoundery(tweetData,boundery);
					System.out.printf("lastError:%f\tnewError:%f\tnewBoundery:%f",lastError, bounderyError[1],bounderyError[0]);
					if (lastError==bounderyError[1]){
						optimized = true;
					}
					boundery = bounderyError[0];
					lastError = bounderyError[1];
					//bounderies = calcBoundery(bounderie1,bounderie2, woordenweightslijst);
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}


			woordenweightslijst = scaleWeightList(woordenweightslijst);
			writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsListSentiment.txt");
		} catch (IOException e1) {
			e1.printStackTrace();
		}



	}

	// sentiment can be removed after a good way of finding out the expected
	// sentiment with an initial calculation of the tweet value.
	public static void PerceptronSingleTweet(String tweet, int sentiment,
			double alpha, int iterations, PrintWriter out) throws IOException {
		Map<String, Double> weightlist = getWeights(tweet, woordenweightslijst);
		double tweetValue = CalculateTweetValue(weightlist, tweet);
		double expectedTweetValue = StandardFunctions.convertExpectedTweetValueToClass(tweetValue);
		System.out.println("tweet           " + tweet);
		System.out.println("weightlist      " + weightlist);
		System.out.println("sentiment       " + sentiment);
		System.out.println("expectedValue   " + expectedTweetValue);
		System.out.println("calculatedValue "
				+ CalculateTweetValue(weightlist, tweet));
		weightlist = runSingle(weightlist, expectedTweetValue, tweet, alpha,
				iterations);
		System.out.println("calculatedValue "
				+ CalculateTweetValue(weightlist, tweet));

		updateWoordenWeightsLijst(weightlist);
	}

	static void updateWoordenWeightsLijst(Map<String, Double> weightlist) {
		double weight;
		weightlist = scaleWeightList(weightlist);
		for (String word : weightlist.keySet()) {
			weight = weightlist.get(word);
			woordenweightslijst.put(word, weight);
		}

	}

	static Map<String, Double> runSingle(Map<String, Double> weightlist,
			double expectedTweetValue, String tweet, double alpha,
			int iterations) throws IOException {
		double tweetValue = 0;
		double error = 0;
		double weight;
		for (int i = 0; iterations - i > 0; i++) {
			tweetValue = CalculateTweetValue(weightlist, tweet);
			error = expectedTweetValue - tweetValue;
			for (String word : weightlist.keySet()) {
				weight = weightlist.get(word);
				weight += alpha * error;
				weightlist.put(word, weight);
			}
		}
		return weightlist;

	}

	public static Map<String, Double> getWeights(String tweet,
			Map<String, Double> weightlist) {
		Map<String, Double> woordenWeights = new HashMap<String, Double>();
		StringTokenizer st = new StringTokenizer(tweet,
				" \r\n\t\f,.!$%^&*()[]{}-=\\;<>/?:_");
		String word;
		// get initial weights of words
		while (st.hasMoreTokens()) {
			word = st.nextToken();

			// look up weight
			if(word.length()>2){
				Double weight = (weightlist.get(word) != null) ? weightlist
						.get(word) : 0;
						woordenWeights.put(word, weight);
			}

		}
		return woordenWeights;
	}

	public static void printWeigthlist() throws IOException {
		writeWeigthsToFile(woordenweightslijst,"updatedWordsWeightsList.txt");
	}

}
